/*
 * Copyright (C) 2025 ttwe77
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class MultiThreadJavaExecutor {
    private static volatile boolean running = true;
    private static AtomicInteger completedCount = new AtomicInteger(0);
    private static AtomicInteger successCount = new AtomicInteger(0);
    private static AtomicInteger failedCount = new AtomicInteger(0);
    private static Instant startTime;
    private static int totalCount;
    private static int threadCount;

    public static void main(String[] args) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        
        try {
            // 显示欢迎信息
            System.out.println("========================================");
            System.out.println("         多线程Java执行器");
            System.out.println("========================================");
            
            // 获取执行次数
            totalCount = getValidatedInput(reader, "请输入要执行的次数: ", "错误：请输入有效的数字！", true);
            
            // 获取线程数
            threadCount = getValidatedInput(reader, "请输入线程数 (1-" + totalCount + "): ", 
                    "错误：请输入有效的线程数！", false);
            
            threadCount = Math.min(threadCount, totalCount);
            threadCount = Math.max(1, threadCount);
            
            System.out.println();
            System.out.println("配置信息:");
            System.out.println("执行次数: " + totalCount);
            System.out.println("线程数: " + threadCount);
            System.out.println("平均每个线程执行: " + (totalCount / threadCount) + " 次");
            System.out.println();
            System.out.println("即将执行 java TripleDoublePinyinKeygen_UUID_AllRandom");
            System.out.println("按回车键开始执行，按 Ctrl+C 取消...");
            reader.readLine();
            
            // 开始执行
            startTime = Instant.now();
            ScheduledExecutorService progressScheduler = Executors.newSingleThreadScheduledExecutor();
            
            // 启动进度显示线程
            progressScheduler.scheduleAtFixedRate(() -> {
                if (running) {
                    updateProgressBar();
                }
            }, 0, 100, TimeUnit.MILLISECONDS);
            
            // 创建线程池执行任务
            boolean success = executeWithThreadPool();
            
            running = false;
            progressScheduler.shutdown();
            
            // 显示最终结果
            System.out.println();
            System.out.println("========================================");
            System.out.println("执行完成！");
            System.out.println("成功: " + successCount.get() + " 次");
            System.out.println("失败: " + failedCount.get() + " 次");
            
            Duration totalTime = Duration.between(startTime, Instant.now());
            double executionsPerSecond = totalCount / (totalTime.toMillis() / 1000.0);
            
            System.out.printf("总耗时: %d分 %d秒%n", 
                totalTime.toMinutes(), totalTime.toSeconds() % 60);
            System.out.printf("执行速度: %.2f 次/秒%n", executionsPerSecond);
            System.out.println("使用线程数: " + threadCount);
            
        } catch (IOException e) {
            System.out.println("输入输出错误: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("发生错误: " + e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                // 忽略关闭错误
            }
        }
    }
    
    private static int getValidatedInput(BufferedReader reader, String prompt, 
                                       String errorMsg, boolean allowEqualZero) throws IOException {
        int value = 0;
        boolean validInput = false;
        
        while (!validInput) {
            System.out.print(prompt);
            String input = reader.readLine();
            
            try {
                value = Integer.parseInt(input.trim());
                if (value < (allowEqualZero ? 0 : 1)) {
                    System.out.println("错误：数值必须" + (allowEqualZero ? "大于等于0" : "大于0") + "！");
                    continue;
                }
                validInput = true;
            } catch (NumberFormatException e) {
                System.out.println(errorMsg);
            }
        }
        return value;
    }
    
    private static boolean executeWithThreadPool() {
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        CountDownLatch latch = new CountDownLatch(totalCount);
        
        // 提交所有任务
        for (int i = 0; i < totalCount; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                try {
                    boolean success = executeSingleJavaCommand(taskNumber);
                    if (success) {
                        successCount.incrementAndGet();
                    } else {
                        failedCount.incrementAndGet();
                    }
                } catch (Exception e) {
                    failedCount.incrementAndGet();
                    System.err.println("任务 " + taskNumber + " 执行异常: " + e.getMessage());
                } finally {
                    completedCount.incrementAndGet();
                    latch.countDown();
                }
            });
        }
        
        try {
            // 等待所有任务完成
            latch.await();
            executor.shutdown();
            return executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
    
    private static boolean executeSingleJavaCommand(int taskNumber) {
        ProcessBuilder processBuilder = new ProcessBuilder("java", "TripleDoublePinyinKeygen_UUID_AllRandom");
        
        try {
            Process process = processBuilder.start();
            
            // 读取输出流（避免阻塞）
            try (BufferedReader outputReader = new BufferedReader(
                new InputStreamReader(process.getInputStream()))) {
                // 清空输出缓冲区
                while (outputReader.readLine() != null) {
                    // 忽略输出内容，避免阻塞
                }
            }
            
            // 读取错误流（避免阻塞）
            try (BufferedReader errorReader = new BufferedReader(
                new InputStreamReader(process.getErrorStream()))) {
                // 清空错误缓冲区
                while (errorReader.readLine() != null) {
                    // 忽略错误内容，避免阻塞
                }
            }
            
            int exitCode = process.waitFor();
            return exitCode == 0;
            
        } catch (IOException | InterruptedException e) {
            System.err.println("任务 " + taskNumber + " 执行失败: " + e.getMessage());
            return false;
        }
    }
    
    private static void updateProgressBar() {
        int completed = completedCount.get();
        int progress = (int) ((completed / (double) totalCount) * 100);
        
        Duration elapsed = Duration.between(startTime, Instant.now());
        long elapsedSeconds = elapsed.getSeconds();
        
        // 计算剩余时间
        long remainingSeconds = 0;
        if (completed > 0 && elapsedSeconds > 0) {
            double speed = completed / (double) elapsedSeconds;
            if (speed > 0) {
                remainingSeconds = (long) ((totalCount - completed) / speed);
            }
        }
        
        // 构建进度条
        StringBuilder progressBar = new StringBuilder();
        progressBar.append("\r[");
        
        int barWidth = 50;
        int progressWidth = (progress * barWidth) / 100;
        
        for (int i = 0; i < barWidth; i++) {
            if (i < progressWidth) {
                progressBar.append("=");
            } else if (i == progressWidth) {
                progressBar.append(">");
            } else {
                progressBar.append(" ");
            }
        }
        
        progressBar.append("] ");
        progressBar.append(String.format("%3d%%", progress));
        progressBar.append(" (");
        progressBar.append(completed);
        progressBar.append("/");
        progressBar.append(totalCount);
        progressBar.append(") ");
        
        // 添加时间信息
        progressBar.append("已用: ");
        progressBar.append(formatTime(elapsedSeconds));
        progressBar.append(" 剩余: ");
        progressBar.append(formatTime(remainingSeconds));
        
        // 添加线程信息
        progressBar.append(" 线程: ");
        progressBar.append(threadCount);
        
        System.out.print(progressBar.toString());
    }
    
    private static String formatTime(long seconds) {
        if (seconds < 60) {
            return String.format("%2ds", seconds);
        } else {
            long minutes = seconds / 60;
            long remainingSeconds = seconds % 60;
            return String.format("%2dm%02ds", minutes, remainingSeconds);
        }
    }
}